<?php
namespace library\widgets;

use idea\ap\Ap;
use idea\mvc\Widget;

/**
 * FormBuilder class file
 * 创建表单
 * @author 宋欢 <iphper@yeah.net>
 * @version $Id: FormBuilder.php 1 2013-04-20 17:11:06Z huan.song $
 * @package library.widgets
 * @since 1.0
 */
class FormBuilder extends Widget
{
	/**
	 * @var string 普通提示标签的class名
	 */
	const CSS_TIPS_NAME = 'formtips';
	
	/**
	 * @var string 错误提醒标签的class名
	 */
	const CSS_ERROR_NAME = 'formerr';
	
	/**
	 * @var string 表单html标签名
	 */
	const HTML_FORM_NAME = 'p';
	
	/**
	 * @var string 标题html标签名
	 */
	const HTML_LABEL_NAME = 'label';
	
	/**
	 * @var string 提醒html标签名
	 */
	const HTML_TIPS_NAME = 'small';
	
	/**
	 * @var array 表单属性
	 */
	protected $_attributes = array();
	
	/**
	 * @var array 表单元素
	 */
	protected $_types = array(
		'text',
		'password',
		'hidden',
		'file',
		'submit',
		'reset',
		'image',
		'button',
		'textarea',
		'img',
		'select',
		'radio',
		'checkbox',
		'fckeditor'
	);

	/**
	 * 执行Widget类，输出内容
	 * @return void
	 */
	public function run()
	{
		$this->_attributes = $this->_tplVars['form']->getAttributes();
		
		$html = '';
		foreach ($this->_tplVars['columns'] as $key => $params) {
			$html .= $this->getHtml()->openTag(self::HTML_FORM_NAME) . "\n";
			if (is_int($key) && is_string($params)) {
				$params = array(
					'name' => $params
				);
			}
			elseif (!is_array($params)) {
				continue;
			}
			elseif (!isset($params['name']) && is_string($key)) {
				$params['name'] = $key;
			}
			
			$this->addTag($html, $params);
			$html .= $this->getHtml()->closeTag(self::HTML_FORM_NAME) . "\n";
		}

		echo $html;
	}
	
	/**
	 * 向HTML串中添加表单元素
	 * @param string $html
	 * @param array $params
	 * @return void
	 */
	public function addTag(&$html, array $params = array())
	{
		if (isset($params['__multi__']) && $params['__multi__']) {
			foreach ($params as $key => $param) {
				if (is_int($key) && is_string($param)) {
					$param = array(
						'name' => $param
					);
				}
				elseif (!is_array($param)) {
					continue;
				}
				elseif (!isset($param['name']) && is_string($key)) {
					$param['name'] = $key;
				}
				
				$this->addTag($html, $param);
			}
			
			return ;
		}
		
		$name = $type = $label = $prompt = $value = '';
		if (isset($params['name'])) {
			$name = $params['name'];
		}

		if (isset($params['type'])) {
			$type = $params['type'];
		}
		elseif (isset($this->_attributes[$name]['type'])) {
			$type = $this->_attributes[$name]['type'];
		}
		
		if (!in_array($type, $this->_types)) {
			continue;
		}
		
		if (isset($params['label'])) {
			$label = $params['label'];
		}
		elseif (isset($this->_attributes[$name]['label'])) {
			$label = $this->_attributes[$name]['label'];
		}
		
		if (isset($params['prompt'])) {
			$prompt = $params['prompt'];
		}
		
		if (isset($params['value'])) {
			$value = $params['value'];
		}
		$value = $this->getValue($name, $value);

		$attributes = isset($params['attributes']) ? (array) $params['attributes'] : array();
		$options = isset($params['options']) ? (array) $params['options'] : array();
		
		$html .= $this->getLabel($name, $label, $prompt);
		$html .= $this->getInput($type, $name, $value, $attributes, $options);
		$html .= "\n";
	}
	
	/**
	 * 获取表单内容
	 * @param string $type
	 * @param string $name
	 * @param string $value
	 * @param array $attributes
	 * @param array $options
	 * @return string
	 */
	public function getInput($type, $name, $value, array $attributes = array(), array $options = array())
	{
		if (method_exists($this, $type)) {
			return $this->$type($name, $value, $attributes, $options);
		}
		elseif (method_exists($this->_tplVars['form'], $type)) {
			return $this->_tplVars['form']->$type($name, $value, $attributes, $options);
		}
		
		return '';
	}

	/**
	 * 通过字段名获取错误提示
	 * @param string $name
	 * @param string $label
	 * @param string $prompt
	 * @return string
	 */
	public function getLabel($name, $label = '', $prompt = '')
	{
		if ($label !== '') {
			$prompt = $this->getPrompt($name, $prompt);
			return $this->getHtml()->tag(self::HTML_LABEL_NAME, array(), $label . $prompt) . "\n";
		}
		
		return '';
	}
	
	/**
	 * 通过字段名获取提示信息，如果有错误信息，优先返回错误信息
	 * @param string $name
	 * @param string $default
	 * @return string
	 */
	public function getPrompt($name, $default = '')
	{
		if (($errMsg = $this->getErrMsg($name)) !== '') {
			return $errMsg;
		}
		
		if ($default !== '') {
			return $this->getHtml()->tag(self::HTML_TIPS_NAME, array('class' => self::CSS_TIPS_NAME), $default);
		}
		
		return '';
	}
	
	/**
	 * 通过字段名获取错误提示
	 * @param string $name
	 * @return string
	 */
	public function getErrMsg($name)
	{
		if ($name === '') {
			return '';
		}

		if (isset($this->_tplVars['errors'][$name])) {
			return $this->getHtml()->tag(self::HTML_TIPS_NAME, array('class' => self::CSS_ERROR_NAME), $this->_tplVars['errors'][$name]);
		}

		return '';
	}
	
	/**
	 * 通过字段名获取字段值，先成页面输出的数据data中获取，如果获取不到，从RGP中获取
	 * @param string $name
	 * @param string $default
	 * @return string
	 */
	public function getValue($name, $default = '')
	{
		if ($name === '') {
			return $default;
		}
		
		if (isset($this->_tplVars['data'][$name])) {
			return $this->_tplVars['data'][$name];
		}
		
		if (($value = Ap::getRequest()->getParam($name, '')) !== '') {
			return $value;
		}
		
		return $default;
	}
	
	/**
	 * 获取表单元素：fckeditor
	 * @param string $name
	 * @param mixed $value
	 * @param array $attributes
	 * @return string
	 */
	public function fckeditor($name, $value, $attributes)
	{
		$toolbar = isset($attributes['toolbar']) ? $attributes['toolbar'] : 'Default';
		$width = isset($attributes['width']) ? (int) $attributes['width'] : 820;
		$height = isset($attributes['height']) ? (int) $attributes['height'] : 550;
		$jsUrl = $this->getView()->base_url . '/static/common/js';
		
		require_once DIR_WEBROOT . '/static/common/js/fckeditor/fckeditor.php';
		$fckeditor = new \FCKeditor($name);
		
		$fckeditor->BasePath = $jsUrl . '/fckeditor/';
		$fckeditor->Config['SkinPath'] = $jsUrl . '/fckeditor/editor/skins/silver/';
		$fckeditor->Config['CustomConfigurationsPath'] = $jsUrl . '/fck-definedbar.js';
		$fckeditor->ToolbarSet = $toolbar;
		$fckeditor->Width  = $width;
		$fckeditor->Height = $height;
		$fckeditor->Value  = $value;
		return $fckeditor->CreateHtml();
	}
}
